package cn.xd.itstack.springframework.beans.factory.support;

import cn.xd.itstack.springframework.beans.factory.BeanFactory;
import cn.xd.itstack.springframework.beans.factory.FactoryBean;
import cn.xd.itstack.springframework.beans.factory.config.BeanDefinition;
import cn.xd.itstack.springframework.beans.factory.config.BeanPostProcessor;
import cn.xd.itstack.springframework.beans.factory.config.ConfigurableBeanFactory;
import cn.xd.itstack.springframework.utils.ClassUtil;
import cn.xd.itstack.springframework.utils.StringValueResolver;


import java.util.ArrayList;
import java.util.List;


/**
 * @Classname AbstractBeanFactory
 * @Description 模板方法
 * @Date 2022/5/10 下午3:44
 * @Created by lvxiaodong
 */
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

    /**
     * BeanPostProcessors to apply in createBean
     */
    private final List<BeanPostProcessor> beanPostProcessors = new ArrayList<BeanPostProcessor>();


    private ClassLoader beanClassLoader = ClassUtil.getClassLoader();


    private final List<StringValueResolver> embeddedValueResolvers = new ArrayList<>();

    /**
     * 优先从单利中获取
     * 获取不到获取Bean定义，创建Bean
     *
     * @param beanName
     * @return
     */
    @Override
    public Object getBean(String beanName) {
        return doGetBean(beanName, null);

    }

    @Override
    public Object getBean(String beanName, Object... args) {
        return doGetBean(beanName, args);
    }


    @Override
    public <T> T getBean(String beanName, Class<T> requestedType) {
        return doGetBean(beanName, requestedType);
    }


    protected <T> T doGetBean(final String beanName, final Object args) {
        Object bean = getSingleton(beanName);
        if (bean != null) {
            return (T) getObjectForBeanInstance(bean, beanName);
        }
        BeanDefinition beanDefinition = getBeanDefinition(beanName);
        bean = createBean(beanName, beanDefinition, args);
        bean = getObjectForBeanInstance(bean,beanName);
        return (T) bean;

    }

    private Object getObjectForBeanInstance(Object bean, String beanName) {
        if(!(bean instanceof FactoryBean)){
            return bean;
        }
        //从缓存中获取
        Object object = getCacheObjectFromFactoryBean(beanName);
        if(object==null){
            FactoryBean<?> factoryBean = (FactoryBean<?>) bean;
            object = getObjectFromFactoryBean(factoryBean, beanName);
        }
        return object;
    }

    @Override
    public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
        beanPostProcessors.remove(beanPostProcessor);
        beanPostProcessors.add(beanPostProcessor);
    }

    public List<BeanPostProcessor> getBeanPostProcessors() {
        return beanPostProcessors;
    }


    protected abstract Object createBean(String beanName, BeanDefinition beanDefinition);

    protected abstract BeanDefinition getBeanDefinition(String beanName);

    protected abstract Object createBean(String beanName, BeanDefinition beanDefinition, Object... args);


    public ClassLoader getBeanClassLoader() {
        return this.beanClassLoader;
    }

    @Override
    public void addEmbeddedValueResolver(StringValueResolver valueResolver){
        this.embeddedValueResolvers.add(valueResolver);
    }

    @Override
    public String resolveEmbeddedValue(String value){
        String result = value;
        for (StringValueResolver resolver : this.embeddedValueResolvers) {
            result = resolver.resolveStringValue(result);
        }
        return result;
    }


}
